/* -------------------------------------------------------------------------- *
   TestWinUnit - Maria Blees (maria.blees@microsoft.com)

   File: TestModuleTest

   This file contains tests for TestModule.
 * -------------------------------------------------------------------------- */
#include "WinUnit.h"

#include "TestModule.h"
#include "TestIdentifier.h"
#include "MockLogger.h"

#include "DllMain.h"
#include "InspectableTestModule.h"

using namespace WinUnitLib;

BEGIN_TEST(TestModuleGetFirstFailsIfModuleNotFound)
{
    wchar_t* fileThatDoesNotExist = L"foo.bar";
    DWORD fileAttributes = ::GetFileAttributesW(fileThatDoesNotExist);
    WIN_ASSERT_EQUAL(INVALID_FILE_ATTRIBUTES, fileAttributes, 
        _T("This test assumes that file foo.bar does not exist."));

    MockLogger logger;
    TestModule testModule(logger, fileThatDoesNotExist);

    TestIdentifier testIdentifier;
    WIN_ASSERT_EQUAL(false, testModule.GetFirst(testIdentifier));

    WIN_ASSERT_EQUAL(1, logger.OutputProgramErrorLineCalled);
    WIN_TRACE("INFO: Next line should indicate that foo.bar could not be found.\n");
    WIN_TRACE(L"OUTPUT: %s\n", logger.OutputProgramErrorLine_msg1);
}
END_TEST

BEGIN_TEST(TestModuleGetFirstFailsIfFilenameNull)
{
    MockLogger logger;
    TestModule testModule(logger, NULL);

    TestIdentifier testIdentifier;
    WIN_ASSERT_EQUAL(false, testModule.GetFirst(testIdentifier));

    WIN_ASSERT_EQUAL(1, logger.OutputProgramErrorLineCalled);

    WIN_TRACE("INFO: Next line should indicate that TestModule::GetFirst fails if module name is NULL.\n");
    WIN_TRACE(L"OUTPUT: %s\n", logger.OutputProgramErrorLine_msg1);
}
END_TEST

BEGIN_TEST(TestModuleGetFirstMustBeCalledBeforeGetNext)
{
    MockLogger logger;
    TestModule testModule(logger, L"foo");

    TestIdentifier testIdentifier;
    WIN_ASSERT_EQUAL(false, testModule.GetNext(testIdentifier));
    WIN_ASSERT_EQUAL(1, logger.OutputProgramErrorLineCalled);
    WIN_TRACE(L"INFO: Next line should indicate that GetFirst must be called before GetNext:\n");
    WIN_TRACE(L"OUTPUT: %s\n", logger.OutputProgramErrorLine_msg1);
}
END_TEST

BEGIN_TEST(TestModuleGetFirstOkayToBeCalledTwice)
{
    // This module is g_hmodule
    wchar_t buffer[MAX_PATH] = L"";
    DWORD charsCopied = GetModuleFileNameW(g_hmodule, buffer, ARRAYSIZE(buffer));
    WIN_ASSERT_WINAPI_SUCCESS(charsCopied != 0, _T("GetModuleFileName failed."));

    MockLogger logger;
    InspectableTestModule testModule(logger, buffer, true);

    TestIdentifier testIdentifier;

    // Call GetFirst and record resulting test name.
    WIN_ASSERT_EQUAL(true, testModule.GetFirst(testIdentifier));
    char testName[100] = "";
    strcpy_s(testName, testIdentifier.TestName);

    // Try calling GetFirst again and see if we get the same answer.
    WIN_ASSERT_EQUAL(true, testModule.GetFirst(testIdentifier));
    WIN_ASSERT_STRING_EQUAL(testName, testIdentifier.TestName);
}
END_TEST

BEGIN_TEST(TestModuleExecuteTestFailsWithNonMatchingHModule)
{
    // This module is g_hmodule
    wchar_t buffer[MAX_PATH] = L"";
    DWORD charsCopied = GetModuleFileNameW(g_hmodule, buffer, ARRAYSIZE(buffer));
    WIN_ASSERT_WINAPI_SUCCESS(charsCopied != 0, _T("GetModuleFileName failed."));

    MockLogger logger;
    InspectableTestModule testModule(logger, buffer, true);

    TestIdentifier testIdentifier((HMODULE)-1, "foo", "foo");
    wchar_t errorString[1024] = L"";
    WIN_ASSERT_FALSE(testModule.ExecuteTest(testIdentifier, errorString, ARRAYSIZE(errorString)));

    WIN_TRACE(_T("INFO: Next line should indicate that HMODULE did not match.\n"));
    WIN_TRACE(L"OUTPUT: %s\n", errorString);
}
END_TEST

BEGIN_TEST(TestModuleExecuteTestFailsIfModuleFailedToLoad)
{
    MockLogger logger;
    TestModule testModule(logger, L"blah.dll");

    TestIdentifier testIdentifier(NULL, "foo", "foo");
    wchar_t errorString[1024] = L"";
    WIN_ASSERT_FALSE(testModule.ExecuteTest(testIdentifier, errorString, ARRAYSIZE(errorString)));

    WIN_TRACE(_T("INFO: Next line should indicate that module %s failed to load.\n"), _T("blah.dll"));
    WIN_TRACE(L"OUTPUT: %s\n", errorString);
}
END_TEST

BEGIN_TEST(TestModuleExecuteTestFailsWithNonxistentExportName)
{
    // This module is g_hmodule
    wchar_t buffer[MAX_PATH] = L"";
    DWORD charsCopied = GetModuleFileNameW(g_hmodule, buffer, ARRAYSIZE(buffer));
    WIN_ASSERT_WINAPI_SUCCESS(charsCopied != 0, _T("GetModuleFileName failed."));

    MockLogger logger;
    InspectableTestModule testModule(logger, buffer, true);

    TestIdentifier testIdentifier(g_hmodule, "foo", "foo");
    wchar_t errorString[1024] = L"";
    WIN_ASSERT_FALSE(testModule.ExecuteTest(testIdentifier, errorString, ARRAYSIZE(errorString)));

    WIN_TRACE(_T("INFO: Next line should indicate that test foo was not found.\n"));
    WIN_TRACE(L"OUTPUT: %s\n", errorString);
}
END_TEST

